﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace Xeml.Document.Contracts
{
    public interface IHierarchicalView
    {
        IEnumerable<TermNode> Nodes { get; }
        TermNode FindNode(IOntologyTerm t);
        TermNode FindNode(string termid);
    }

    public class TermNode
    {
        public bool IsContainer { get; internal set; }
        public IOntologyTerm Term { get; private set; }
        public ReadOnlyCollection<AttributedRelation<TermNode>> Childs { get; private set; }
        public TermNode Parent { get; private set; }
        public string Label { get; set; }
        public bool IsRoot { get { return Parent == null; } }
        public string Path
        {
            get
            {
                if (IsRoot)
                {
                    return Label;
                }
                else
                    return Parent.Path + "." + Label;
            }
        }

        private List<AttributedRelation<TermNode>> _childs;
        private TermNode()
        {
            _childs = new List<AttributedRelation<TermNode>>();
            Childs = new ReadOnlyCollection<AttributedRelation<TermNode>>(_childs);

        }

        public static TermNode CreateContainerNode(string label)
        {
            TermNode ret = new TermNode();
            ret.IsContainer = true;
            ret.Label = label;
            return ret;
        }

        public static TermNode CreateNode(IOntologyTerm t)
        {
            TermNode ret = new TermNode();
            ret.IsContainer = false;
            ret.Label = t.Prototype.Name;
            ret.Term = t;
            return ret;
        }

        public void AddSubNode(TermNode tn, string attribute)
        {
            _childs.Add(new AttributedRelation<TermNode>(attribute, tn));
            tn.Parent = this;
        }

        public void RemoveParent()
        {
            Parent = null;
        }

        public void SortChildren(Comparison<AttributedRelation<TermNode>> comparison)
        {
            _childs.Sort(comparison);

            foreach (var item in _childs)
            {
                item.Relation.SortChildren(TermNode.CompareAttributedRelationByTermNodeLabel);
            }
        }

        public static int CompareAttributedRelationByTermNodeLabel(AttributedRelation<TermNode> x, AttributedRelation<TermNode> y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    // ...and y is not null, compare the 
                    // lengths of the two strings.
                    //
                    int retval = x.Relation.Label.CompareTo(y.Relation.Label);

                    if (retval != 0)
                    {
                        // If the strings are not of equal length,
                        // the longer string is greater.
                        //
                        return retval;
                    }
                    else
                    {
                        // If the strings are of equal length,
                        // sort them with ordinary string comparison.
                        //
                        return x.Relation.Label.CompareTo(y.Relation.Label);
                    }
                }
            }
        }

        public static int CompareTermNodeByLabel(TermNode x, TermNode y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    // ...and y is not null, compare the 
                    // lengths of the two strings.
                    //
                    int retval = x.Label.CompareTo(y.Label);

                    if (retval != 0)
                    {
                        // If the strings are not of equal length,
                        // the longer string is greater.
                        //
                        return retval;
                    }
                    else
                    {
                        // If the strings are of equal length,
                        // sort them with ordinary string comparison.
                        //
                        return x.Label.CompareTo(y.Label);
                    }
                }
            }
        }
    }

    public class AttributedRelation<T>
    {
        public string Attribute { get; private set; }
        public T Relation { get; private set; }

        public AttributedRelation(string attr, T relation)
        {
            Attribute = attr;
            Relation = relation;
        }
    }
}
